package lil.llahn.security.common.symmetry;

import lil.llahn.security.common.utils.Base64;
import lombok.extern.slf4j.Slf4j;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.security.SecureRandom;

/**
 * @ClassName: DESSecurityTools
 * @Description: TODO Data Encryption Standard - 数据加密标准
 *      DES是一种对称加密算法，所谓对称加密算法即：加密和解密使用相同密钥的算法。
 *      DES加密算法出自IBM的研究，后来被美国政府正式采用，之后开始广泛流传，但是近些年使用越来越少，因为DES使用56位密钥，以现代计算能力，24小时内即可被破解。
 *      虽然如此，在某些简单应用中，我们还是可以使用DES加密算法，本文简单讲解DES的JAVA实现。
 *
 * @Date: 2019/11/8 16:23
 * @Auther: lil
 */
@Slf4j
public class DESSecurityTools {
    private final static String KEY_DES = "DES";

    public static String init(){
        return init(null);
    }
    /**
     * 初始化秘钥
     * @param arg 字符串参数
     * @return
     */
    public static String init(String arg){
        try{
            SecureRandom secure = null;
            if(arg != null) secure = new SecureRandom(Base64.decoderToByte(arg));
            else secure = new SecureRandom();
            KeyGenerator generator = KeyGenerator.getInstance(KEY_DES);
            generator.init(secure);
            SecretKey key = generator.generateKey();
            return Base64.encoderToString(key.getEncoded());
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * todo 加密
     * @param data
     * @param key
     * @return
     */
    public static String encryptDESByKey(String data, String key){
        try{
            SecureRandom random = new SecureRandom();
            DESKeySpec desKey = new DESKeySpec(key.getBytes());
            //创建一个密匙工厂，然后用它把DESKeySpec转换成
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_DES);
            // 将DESKeySpec对象转换成SecretKey对象
            SecretKey securekey = keyFactory.generateSecret(desKey);
            //Cipher对象实际完成加密操作
            Cipher cipher = Cipher.getInstance(KEY_DES);
            //用密匙初始化Cipher对象
            cipher.init(Cipher.ENCRYPT_MODE, securekey, random);
            return Base64.encoderToString(cipher.doFinal(data.getBytes()));
        }catch (Exception e){
            log.error("Failed to encryptDESByKey data.\r\ndata={}\r\nsalt:{}", data, key, e);
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    public static String decryptDESByKey(String data, String key){
        try{
            SecureRandom random = new SecureRandom();
            DESKeySpec desKey = new DESKeySpec(key.getBytes());
            //创建一个密匙工厂，然后用它把DESKeySpec转换成
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(KEY_DES);
            // 将DESKeySpec对象转换成SecretKey对象
            SecretKey securekey = keyFactory.generateSecret(desKey);
            //Cipher对象实际完成加密操作
            Cipher cipher = Cipher.getInstance(KEY_DES);
            //用密匙初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, securekey, random);
            return new String(cipher.doFinal(Base64.decoderToByte(data)));
        }catch (Exception e){
            log.error("Failed to decryptDESByKey data.\r\ndata={}\r\nsalt:{}", data, key, e);
            throw new RuntimeException(e.getMessage(), e);
        }
    }

}
